package com.cbtx.utils

import android.text.TextUtils
import android.util.Log
import java.io.*
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

/**
 * author : joker.peng
 * e-mail : joker@fiture.com
 * date   : 2021/7/1 12:35 PM
 * desc   :
 */
object FileTool {

    private const val TAG = "FileTools"

    fun isFileExist(filePath: String?): Boolean {
        var result = false
        val file = File(filePath)
        if (file != null && file.exists() && file.isFile) {
            result = true
        }
        return result
    }


    fun isDirExist(dirPath: String?): Boolean {
        var result = false
        val dir = File(dirPath)
        if (dir != null && dir.exists() && dir.isDirectory) {
            result = true
        }
        return result
    }

    fun getFileNames(dirPath: String?): Array<String?>? {
        var files: Array<String?>? = null
        if (isDirExist(dirPath)) {
            val dir = File(dirPath)
            files = dir.list()
        }
        return files
    }

    fun getFiles(dirPath: String?): Array<File?>? {
        var files: Array<File?>? = null
        if (isDirExist(dirPath)) {
            val dir = File(dirPath)
            files = dir.listFiles()
        }
        return files
    }


    fun getContent(file: String?): String? {
        val sb = StringBuffer("")
        if (isFileExist(file)) {
            try {
                val buf = BufferedReader(FileReader(file))
                var line: String? = ""
                while (buf.readLine().also { line = it } != null) {
                    sb.append(line)
                }
                buf.close()
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return sb.toString()
    }

    /**
     * create file
     *
     * @param file path
     * @param file content
     */
    fun createNewFile(file: String?, content: String?) {
        try {
            if (!isFileExist(file)) {
                val newFile = File(file)
                newFile.createNewFile()
            }
            if (!TextUtils.isEmpty(content)) {
                write(file, content, false)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    fun creatDirectory(path: String) {
        val dir = File(path)
        Log.d(TAG, "creat dir $path")
        if (!dir.exists() || !dir.isDirectory) {
            if (dir.mkdirs()) {
                dir.setExecutable(true, false)
                dir.setReadable(true, false)
                dir.setWritable(true, false)
                Log.d(TAG, "create directory success---$path")
            } else {
                Log.d(TAG, "create directory fail---$path")
            }
        }
    }


    fun updateFile(filePath: String, content: String?): Boolean {
        val result = false
        try {
            if (!isFileExist(filePath)) {
                Log.d(TAG, "file not exist---$filePath")
            } else {
                write(filePath, content, false)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return result
    }


    fun write(filename: String?, content: String?, isAppend: Boolean) {
        try {
            val fw = FileWriter(filename, isAppend)
            fw.write(content)
            fw.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }


    fun delete(filename: String?): Boolean {
        var result = false
        val file = File(filename)
        result = if (file.exists()) {
            file.delete()
        } else {
            true
        }
        return result
    }


    fun deleteFiles(path: String) {
        val dir = File(path)
        if (dir != null && dir.exists() && dir.isDirectory) {
            val files = dir.list()
            if (files != null && files.size > 0) {
                for (file in files) {
                    delete(path + File.separator + file)
                }
            }
        }
    }

    /**
     * move file
     *
     * @param srcFile
     * @param dirFile
     * @return
     */
    fun mvFile(srcFile: String, dirFile: String) {
        val commond = "mv $srcFile $dirFile"
        doCommand(commond)
        if (changeMode(dirFile, 777) != 0) {
            val file = File(dirFile)
            file.setExecutable(true, false)
            file.setReadable(true, false)
            file.setWritable(true, false)
        }
    }

    /** */
    /**  */
    /**
     * 文件重命�?
     *
     * @param path    文件目录
     * @param oldname 原来的文件名
     * @param newname 新文件名
     */
    fun renameFile(path: String, oldname: String, newname: String) {
        if (oldname != newname) { // 新的文件名和以前文件名不同时,才有必要进行重命�?
            val oldfile = File("$path/$oldname")
            val newfile = File("$path/$newname")
            if (!oldfile.exists()) {
                return  // 重命名文件不存在
            }
            if (newfile.exists()) { // 若在该目录下已经有一个文件和新文件名相同，则不允许重命名
                println(newname + "已经存在�?")
            } else {
                oldfile.renameTo(newfile)
                newfile.setExecutable(true, false)
                newfile.setReadable(true, false)
                newfile.setWritable(true, false)
            }
        } else {
            println("新文件名和旧文件名相�?...")
        }
    }

    /**
     * change file mode---now using Runtime, no ProcessBuilder, because it is
     * failed.
     *
     * @param mode
     * @return
     */
    fun changeMode(file: String, mode: Int): Int {
        var status = -1
        val commond = "chmod $mode $file"
        status = doCommand(commond)
        return status
    }

    /**
     * execute instruction
     *
     * @param command
     * @return
     */
    fun doCommand(command: String): Int {
        var status = -1
        for (i in 0..9) {
            try {
                Log.d(TAG, "set command --- $command")
                val runtime = Runtime.getRuntime()
                val proc = runtime.exec(command)
                try {
                    status = proc.waitFor()
                } catch (e: InterruptedException) {
                    Log.d(TAG, "set command failed--------------")
                    e.printStackTrace()
                }
                if (status == 0) {
                    Log.d(TAG, "set chmod succeed$i")
                    break
                } else {
                    status = -1
                    Log.d(TAG, "set chmod failed.")
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return status
    }

    fun copyFile(oldPath: String, newPath: String): Boolean {
        var flag = false
        try {
            Log.i("Huan", "old path ==$oldPath")
            Log.i("Huan", "new path ==$newPath")
            var bytesum = 0
            var byteread = 0
            val oldfile = File(oldPath)
            if (oldfile.exists()) {
                Log.i("Huan", "old path ==cunzai")
                val inStream: InputStream = FileInputStream(oldPath)
                val fs = FileOutputStream(newPath)
                val buffer = ByteArray(1024)
                while (inStream.read(buffer).also { byteread = it } != -1) {
                    bytesum += byteread
                    fs.write(buffer, 0, byteread)
                }
                inStream.close()
                flag = true
            }
        } catch (e: Exception) {
            Log.i("ad", "copy error")
            e.printStackTrace()
        }
        return flag
    }

    fun getFileMD5(filePath: String?): String? {
        var md5: String? = ""
        val file = File(filePath)
        if (file.exists()) {
            val messageDigest: MessageDigest
            try {
                messageDigest = MessageDigest.getInstance("MD5")
                val `in`: InputStream = FileInputStream(file)
                val cache = ByteArray(1024)
                var nRead = 0
                while (`in`.read(cache).also { nRead = it } != -1) {
                    messageDigest.update(cache, 0, nRead)
                }
                `in`.close()
                val data = messageDigest.digest()
                md5 = byteToHex(data)
            } catch (e: NoSuchAlgorithmException) {
                e.printStackTrace()
                md5 = ""
            } catch (e: IOException) {
                e.printStackTrace()
                Log.d(TAG, "IOException-----$e")
                md5 = ""
            }
        }
        return md5
    }

    fun byteToHex(bytes: ByteArray): String? {
        val hexDigits = charArrayOf(
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f'
        )
        val stringbuffer = StringBuffer(2 * bytes.size)
        for (b in bytes) {
            val c0 = hexDigits[b.toInt() ushr 4 and 0xf]
            val c1 = hexDigits[b.toInt() and 0xf]
            stringbuffer.append(c0)
            stringbuffer.append(c1)
        }
        return stringbuffer.toString()
    }
}